﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufPushButton.h"
#include "GnufUiCommonDef.h"
#include "GnufItemEvents.h"
#include "GnufSubject.h"
#include "GnufArrangementAreaContent.h"

namespace gnuf {

    class QtWelcomePanelEx;
    class QtProjectBlock;
    class QtWelcomePanelLoginWidget;
    class QtWelcomePanelLastestOpenedList;
    class Info;
    class WelcomePanelProjectBlock;
    class WelcomePanelPushButton;
    class WelcomePanelSampleBlock;
    class WelcomePanelSamplePushButton;
    class ButtonAppearanceSetting;
    class WelcomePanelEx;
    class Text;
    class Block;
    class Color;
    class TreeBoard;
    class TreeNode;
    class ArrangementAreaEvent;
    class QtSampleBlock;

    class GNUF_BASE_EXPORT IWelcomePanelEventHandler
    {
    public:
        virtual void onWelcomePanelButtonClicked(WelcomePanelPushButton* button) {}
        virtual void onWelcomePanelLastestOpenedListClicked(TreeNode*) {}
        virtual void onWelcomePanelMakeLoginQtWidget(QWidget **) {}
    };

    class GNUF_BASE_EXPORT WelcomePanelLastestOpenedList
    {
        GNUF_WATCHABLE_OBJECT(WelcomePanelLastestOpenedList)
    public:
        struct LastestOpenedRecord
        {
            LastestOpenedRecord(
                const std::wstring & name,
                const std::wstring & date,
                const std::wstring & address,
                const gcmp::Any& userData = gcmp::anyimpl::empty_any())
                : Name(name), Date(date), Address(address), UserData(userData) {}
            bool operator==(const LastestOpenedRecord& other) const
            {
                return (this->Name == other.Name)
                    && (this->Date == other.Date)
                    && (this->Address == other.Address);
            }
            const std::wstring Name;
            const std::wstring Date;
            const std::wstring Address;
            gcmp::Any UserData;
        };

    public:
        WelcomePanelLastestOpenedList(const std::wstring& caption, IItemEventHandler*);
        ~WelcomePanelLastestOpenedList() {}

        const std::wstring& caption() const { return m_caption; }
        struct Setting
        {
            Margin ContentsMargin = { 0,0,0,20 };
            int CaptionIndent = 0;
            int Spacing = 16;
            int MinimumWidth = 500;
            int MaximumWidth = 996;
            int FontSize = 20;
        } appearance;

        Toolbar* toolbar() { return m_toolbar.get(); }
        TreeBoard* lastestOpenedList() { return m_lastestOpenedList; }
        void setQtItem(QtWelcomePanelLastestOpenedList* qtItem) { m_qtItem = qtItem; }

        void refresh(const std::list<LastestOpenedRecord>&);
        const std::list<LastestOpenedRecord>& data() const { return m_data; }
        void remove(const LastestOpenedRecord&);

        void setEmptyListBackgroundImage(const std::wstring& emptyListBackgroundImagePath, const std::wstring& emptyListBackgroundImageName);
        const std::wstring& emptyListBackgroundImage() const { return m_emptyListBackgroundImage.get(m_emptyListBackgroundImageName, EIconStatus::eDefault);; }

        void setEmptyListText(const std::wstring& emptyListText) { m_emptyListText = emptyListText; }
        const std::wstring& emptyListText() const { return m_emptyListText; }

    private:
        friend class WelcomePanelEx;
        void initAppearanceSetting();

    private:
        QtWelcomePanelLastestOpenedList* m_qtItem;
        std::wstring m_caption;
        gcmp::OwnerPtr<Toolbar> m_toolbar;
        TreeBoard* m_lastestOpenedList;
        std::list<LastestOpenedRecord> m_data;
        std::wstring m_emptyListBackgroundImageName;
        Icon m_emptyListBackgroundImage;
        std::wstring m_emptyListText;
    };

    class GNUF_BASE_EXPORT WelcomePanelPushButton final : public PushButton
    {
    public:
        explicit WelcomePanelPushButton(gcmp::OwnerPtr<Info>& info, Item* parent);
        ~WelcomePanelPushButton() {}

        void setBlock(WelcomePanelProjectBlock* block);
        inline WelcomePanelProjectBlock* getBlock() const { return m_block; }

    private:
        WelcomePanelProjectBlock* m_block;
    };

    class GNUF_BASE_EXPORT WelcomePanelProjectBlock final : public gcmp::WeakReferenceable
    {
        CANNOT_COPY_OR_ASSIGN(WelcomePanelProjectBlock)
    public:
        explicit WelcomePanelProjectBlock(const std::wstring& caption, WelcomePanelEx* parent);
        ~WelcomePanelProjectBlock();

        WelcomePanelPushButton* addButton(gcmp::OwnerPtr<Info>& info);
        inline const std::vector<gcmp::OwnerPtr<WelcomePanelPushButton>>& getButtons() const { return m_buttonVec; }
        std::vector< WelcomePanelPushButton *> getRawButtons();

        inline std::wstring getCaption() const { return m_caption; }
        struct Setting
        {
            Margin ContentsMargin = { 0,0,0,0 };
            int Spacing = 24;
            int FontSize = 20;
            int TitleSpacing = 16;
        } appearance;

        inline const ButtonAppearanceSetting* buttonAppearanceSetting() const;

    private:
        friend class WelcomePanelEx;
        void setStyle();

        std::wstring m_caption;
        gcmp::OwnerPtr<Toolbar> m_toolbar;
        std::vector<gcmp::OwnerPtr<WelcomePanelPushButton>> m_buttonVec;
    };

    class GNUF_BASE_EXPORT WelcomePanelSamplePushButton final : public PushButton
    {
    public:
        explicit WelcomePanelSamplePushButton(gcmp::OwnerPtr<Info>& info, Item* parent);
        ~WelcomePanelSamplePushButton() {}

        void setBlock(WelcomePanelSampleBlock* block);
        inline WelcomePanelSampleBlock* getBlock() const { return m_block; }

    private:
        WelcomePanelSampleBlock* m_block;
    };

    class GNUF_BASE_EXPORT WelcomePanelSampleBlock final : public gcmp::WeakReferenceable
    {
        CANNOT_COPY_OR_ASSIGN(WelcomePanelSampleBlock)
    public:
        explicit WelcomePanelSampleBlock(const std::wstring& caption, WelcomePanelEx* parent);
        ~WelcomePanelSampleBlock();

        WelcomePanelSamplePushButton* addButton(gcmp::OwnerPtr<Info>& info);
        inline const std::vector<gcmp::OwnerPtr<WelcomePanelSamplePushButton>>& getButtons() const { return m_buttonVec; }
        std::vector< WelcomePanelSamplePushButton *> getRawButtons();

        inline std::wstring getCaption() const { return m_caption; }
        struct Setting
        {
            Margin ContentsMargin = { 0,0,0,0 };
            int Spacing = 24;
            int FontSize = 20;
            int TitleSpacing = 8;
        } appearance;

        inline const ButtonAppearanceSetting* buttonAppearanceSetting() const;

        void setQtSampleBlock(QtSampleBlock* block) { m_qtSampleBlock = block; };
        std::wstring getCaptionForTest() const;
    private:
        friend class WelcomePanelEx;
        void setStyle();

        std::wstring m_caption;
        gcmp::OwnerPtr<Toolbar> m_toolbar;
        std::vector<gcmp::OwnerPtr<WelcomePanelSamplePushButton>> m_buttonVec;
        QtSampleBlock* m_qtSampleBlock = nullptr;

    };

    class GNUF_BASE_EXPORT WelcomePanelLoginBlock final
    {
        GNUF_WATCHABLE_OBJECT(WelcomePanelLoginBlock)
    public:
        explicit WelcomePanelLoginBlock(IItemEventHandler*);
        ~WelcomePanelLoginBlock() {}

    public:
        Block* customizeBlock();
        Toolbar* customizeToolBar();
        bool hasCustomizeToolbar() const { return m_customizeToolbar.get() != nullptr; }

        void setText(const std::wstring&);
        const std::wstring text() const;
        Text* textControl() { return m_text; }

        void setLoginButtonInfo(const Info&);
        const Info* loginButtonInfo() const;
        ButtonEx* loginButton() { return m_loginBtn; }

        void setApplyTrialButtonInfo(const Info&);
        const Info* applyTrialButtonInfo() const;
        ButtonEx* applyTrialButtonButton() { return m_applyTrialBtn; }

        Toolbar* toolbar() { return m_toolbar.get(); }

        Margin& rMargin() { return m_margin; }
        const Margin& margin() const { return m_margin; }

        const Color* backgroundColor() const { return m_backgroundColor.get(); }
        void setBackgroundColor(const Color& color);

        void refresh();

    private:
        void initialize();
        void initContents();
        void initTextAppearanceSetting();
        void initLoginButtonAppearanceSetting();
        void initApplyTrialButtonAppearanceSetting();

    private:
        gcmp::OwnerPtr<Toolbar> m_customizeToolbar;
        gcmp::OwnerPtr<Toolbar> m_toolbar;
        Text* m_text;
        Block* m_block;
        ButtonEx *m_loginBtn, *m_applyTrialBtn;
        QtWelcomePanelLoginWidget* m_loginBlock;
        Margin m_margin;
        gcmp::OwnerPtr<Color> m_backgroundColor;
    };

    class GNUF_BASE_EXPORT WelcomePanelEx final
        : public ArrangementAreaContent , public IItemEventHandler, public Subject<IWelcomePanelEventHandler>
    {
        CANNOT_COPY_OR_ASSIGN(WelcomePanelEx)
    public:
        explicit WelcomePanelEx();
        ~WelcomePanelEx();

        static const std::wstring & key();

        void initialize();

        inline WelcomePanelLastestOpenedList* getRecentList() { return m_recentList.get(); }
        inline const WelcomePanelLastestOpenedList* getRecentList() const { return m_recentList.get(); }

        /// \brief caption关键字说明，支持自定义的Caption
        /// "DC" : "协同项目"
        /// "Sample" : L"示例项目"
        /// "SampleGac" : "示例构件"
        /// "Local" : "本地项目"
        /// "Open" : "打开"
        /// "New" : "新建"
        WelcomePanelProjectBlock* addProjectBlock(const std::wstring& caption);
        inline const std::vector<gcmp::OwnerPtr<WelcomePanelProjectBlock>>& getProjectBlocks() const { return m_projectBlockVec; }
        std::vector< WelcomePanelProjectBlock * > getRawProjectBlocks();

        /// \brief caption关键字说明，支持自定义的Caption
        /// "DC" : "协同项目"
        /// "Sample" : L"示例项目"
        /// "SampleGac" : "示例构件"
        /// "Local" : "本地项目"
        /// "Open" : "打开"
        /// "New" : "新建"
        WelcomePanelSampleBlock* addSampleBlock(const std::wstring& caption);
        inline const std::vector<gcmp::OwnerPtr<WelcomePanelSampleBlock>>& getSampleBlocks() const { return m_sampleBlockVec; }
        std::vector< WelcomePanelSampleBlock * > getRawSampleBlocks();

        inline WelcomePanelLoginBlock* loginBlock() { return m_welcomePanelLoginBlock.get(); }

        Margin& rMargin() { return m_margin; }
        const Margin& margin() const { return m_margin; }

        int& rSpacing() { return m_spacing; }
        const int& spacing() const { return m_spacing; }
        
        void setLoggedIn(bool);
        bool isLoggedIn() const { return (m_loggedIn > 0); }

        void setBackgroundImage(const std::wstring& backgroundPath, const std::wstring& backgroundImageName);
        const std::wstring& backgroundImage() const { return m_backgroundImage.get(m_backgroundImageName, EIconStatus::eDefault); }

    protected:
        // Inherits from ArrangementAreaContent...
        virtual QWidget * qtWidget() override;
        virtual void onPostVisibilityChanged() override;
        virtual void onPostConnectedWithArrangementArea() override;
        virtual void onPreDisconnectedFromArrangementArea() override;
        virtual void onPostGeometryChanged() override;
        virtual void onEvent(ArrangementAreaEvent*) override;

        // Inherits from ItemEventHandler...
        virtual void onClicked(Item*) override;
        virtual void onTreeItemDbClicked(TreeNode*) override;
    private:
        void refreshAppearance();

        QtWelcomePanelEx* m_qtWelcomePanel;
        gcmp::OwnerPtr<WelcomePanelLastestOpenedList> m_recentList;
        std::vector<gcmp::OwnerPtr<WelcomePanelProjectBlock>> m_projectBlockVec;
        std::vector<gcmp::OwnerPtr<WelcomePanelSampleBlock>> m_sampleBlockVec;
        gcmp::OwnerPtr<WelcomePanelLoginBlock> m_welcomePanelLoginBlock;
        int m_loggedIn; // -1:logged-out, 0:uninitialized, 1:logged-in
        Margin m_margin;
        int m_spacing;
        std::wstring m_backgroundImageName;
        Icon m_backgroundImage;
    };

}
